package cn.ywang.spring.customized.framework.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 默认使用JDK动态代理
 * 1. 先要实现invocationHandler
 *
 * @author BeatificWang
 */
public class AopProxy implements InvocationHandler {

	/**
	 * Aop配置，存储 被代理方法，代理类和代理方法
	 */
	private AopConfig aopConfig;

	/**
	 * 被代理类
	 */
	private Object target;

	/**
	 * 传入原生对象，获得代理类
	 *
	 * @param instance
	 * @return
	 */
	public Object getProxy(Object instance) {
		// 此处是为了保存原生对象（被代理类对象）
		this.target = instance;
		Class<?> clazz = instance.getClass();
		return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
	}

	/**
	 * 调用结果
	 *
	 * @param proxy  代理对象
	 * @param method 代理对象调用的接口方法（代理方法），声明类可能是代理接口的父类接口
	 * @param args   方法参数
	 * @return 方法执行结果
	 * @throws Throwable
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// 获取被代理类的原生方法
		Method targetMethod = this.target.getClass().getMethod(method.getName(), method.getParameterTypes());

		// 作业：利用AOP思想实现一个TransactionManager
		// 通过反射拿到method的异常类型
		targetMethod.getExceptionTypes();

		// aspect的前置方法,在调用原始方法targetMethod之前调用
		if (this.aopConfig.contains(targetMethod)) {
			AopConfig.Aspect aspect = this.aopConfig.get(targetMethod);
			aspect.getPoints()[0].invoke(aspect.getAspect());
		}
		// 调用原始方法targetMethod
		System.out.println("调用原始方法");
		Object object = method.invoke(this.target, args);
		// 后置方法,调用原始方法targetMethod之后调用
		if (this.aopConfig.contains(targetMethod)) {
			AopConfig.Aspect aspect = this.aopConfig.get(targetMethod);
			aspect.getPoints()[1].invoke(aspect.getAspect());
		}
		return object;
	}

	public AopConfig getAopConfig() {
		return this.aopConfig;
	}

	public void setAopConfig(AopConfig aopConfig) {
		this.aopConfig = aopConfig;
	}

	public Object getTarget() {
		return this.target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}
}
